WebWorker 基础
WebWorker 的作用
- JS 是单线程,复杂计算会卡住页面
- 而 Web Worker 可以开一个后台线程,不阻塞 UI
- 也就是复杂计算可以交给 WebWorker 去做,以此优化 UI 卡顿
- 注意:不能操作 DOM,只能通过 postMessage 通信,且通信是拷贝传递(结构化克隆),不是共享
WebWorker 核心语法
shell
# 创建
new Worker('worker.js')
# 发送
worker.postMessage(数据)
# 接收
worker.onmessage = fn
# 关闭
worker.terminate()实际用途
shell
# 适合
大量CPU 密集型计算,不阻塞 UI 渲染
后台异步处理,页面照常交互
数据解析、转换、加工
大文件处理、分片、校验
定时 / 循环任务,不卡页面
# 不适合
操作 DOM、访问 window/document
频繁、极轻量的小计算(通信开销更大)
直接操作 localStorage/indexedDB(可发消息让主线程做)
弹框、路由跳转、UI 相关逻辑
# 总结
凡是算得多、跑得久、不碰 DOM的任务,都适合丢给 WebWorker。典型业务场景
shell
大数据量表格排序、筛选、聚合计算
复杂图表数据预处理
大量 JSON/XML/Excel 解析与格式化
前端加密、解密、签名计算
图片 / 音频前端压缩、格式转换
大文件MD5/SHA 校验、分片上传计算
长列表虚拟滚动数据预处理
复杂数学公式、物理模拟、3D 计算
日志 / 埋点数据本地批量统计
爬虫类数据抓取与解析(同域下)
后台定时数据同步、缓存更新
代码编辑器语法检查、格式化
大量正则匹配、文本替换、分词处理
游戏引擎物理计算、AI 逻辑
音视频转码、切片、帧处理
在线文档协同编辑冲突计算注意
测试的时候不能使用本地的html文件, 需要启动本地服务:http-server 或者放在启动本地环境的 vue/react 项目中测试
通信一则
主线程与 Worker 之间只能用 postMessage / onmessage 交换数据;载荷使用 结构化克隆算法 拷贝(函数、Symbol、部分内置对象不可克隆)。需要共享大块缓冲区时可考虑 Transferable(如 ArrayBuffer)减少拷贝开销。
Vite 与 Vue3:内联多 Worker
无需单独 worker.js 文件时,可用 Blob + URL.createObjectURL 动态生成 Worker,便于在单文件组件里调试。多个 Worker 可并行分担 CPU 密集任务,主线程汇总结果。
示例:三段区间并行累加
html
<template>
<div class="p-6">
<h2>Vue3 + 多 Web Worker 并发计算</h2>
<p class="mt-4">总计算结果:{{ total }}</p>
<button @click="startCalc" class="mt-4 px-4 py-2 bg-blue-500 text-white">
开始计算
</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const total = ref(0);
function createInlineWorker(workerFunc) {
const blob = new Blob([`(${workerFunc.toString()})()`], {
type: "application/javascript",
});
return new Worker(URL.createObjectURL(blob));
}
const workerLogic = () => {
self.onmessage = (e) => {
const { start, end } = e.data;
let sum = 0;
for (let i = start; i <= end; i++) {
sum += i;
}
self.postMessage({ result: sum });
};
};
const startCalc = () => {
const results = [];
let finishedCount = 0;
const w1 = createInlineWorker(workerLogic);
const w2 = createInlineWorker(workerLogic);
const w3 = createInlineWorker(workerLogic);
w1.postMessage({ start: 1, end: 1000000 });
w2.postMessage({ start: 1000001, end: 2000000 });
w3.postMessage({ start: 2000001, end: 3000000 });
function onMessage(e) {
results.push(e.data.result);
finishedCount++;
if (finishedCount === 3) {
total.value = results.reduce((a, b) => a + b, 0);
w1.terminate();
w2.terminate();
w3.terminate();
}
}
w1.onmessage = onMessage;
w2.onmessage = onMessage;
w3.onmessage = onMessage;
};
</script>三段结果分别为 500000500000、1500000500000、2500000500000,相加得 4500001500000。生产环境若构建工具支持(如 Vite ?worker),优先独立 Worker 文件以便浏览器缓存与 Tree-shaking。
